package models;

import models.exception.DataModificationException;
import siena.*;

import javax.persistence.Lob;
import java.util.ArrayList;
import java.util.List;

public class Card extends Model {

    @Id
    private Long id;

    @Lob
    private String question;

    @Lob
    private String answer;


    @Filter("card")
    private Query<Evaluation> evaluations;

    private Long deckId;

    public Card(Deck deck, String question, String answer) {
        this.question = question;
        this.answer = answer;
        this.deckId = deck.id;
    }

    @Override
    public void insert() {
        verifyLegalSaveState();
        super.insert();
    }


    @Override
    public void update() {
        verifyLegalSaveState();
        super.update();
    }


    @Override
    public void delete() {

        if (inOngoingGame()) {
            throw new DataModificationException("Unable to delete card (card.id=" + id + "). "
                    + "Reason: card belongs to game");
        }

        super.delete();
    }

    public boolean inOngoingGame() {
        boolean inOngoingGame = false;
        for (Game game : getGames()) {
            if (game.completed == false) {
                inOngoingGame = true;
            }
        }
        return inOngoingGame;
    }

    private static Query<Card> all() {
        return Model.all(Card.class);
    }

    public static List<Card> findAll() {
        return all().fetch();
    }


    public static Card findById(Long id) {
        return all().filter("id", id).get();
    }

    public static List<Card> findByDeck(Deck deck) {
        return all().filter("deckId", deck.id).fetch();
    }

    public List<Game> getGames() {
        List<Evaluation> evals = Model.all(Evaluation.class).filter("cardId", id).fetch();
        List<Game> games = new ArrayList<Game>();
        for (Evaluation eval : evals) {
            games.add(eval.game);
        }
        return games;
    }

    public String toString() {
        return question;
    }

    public boolean isEmpty() {
        return question.trim().equals("") && answer.trim().equals("");
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;

        Card card = (Card) o;

        if (answer != null ? !answer.equals(card.answer) : card.answer != null) return false;
        if (deckId != null ? !deckId.equals(card.deckId) : card.deckId != null) return false;
        if (evaluations != null ? !evaluations.equals(card.evaluations) : card.evaluations != null) return false;
        if (id != null ? !id.equals(card.id) : card.id != null) return false;
        if (question != null ? !question.equals(card.question) : card.question != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + (id != null ? id.hashCode() : 0);
        result = 31 * result + (question != null ? question.hashCode() : 0);
        result = 31 * result + (answer != null ? answer.hashCode() : 0);
        result = 31 * result + (evaluations != null ? evaluations.hashCode() : 0);
        result = 31 * result + (deckId != null ? deckId.hashCode() : 0);
        return result;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getQuestion() {
        return question;
    }

    public void setQuestion(String question) {
        this.question = question;
    }

    public String getAnswer() {
        return answer;
    }

    public void setAnswer(String answer) {
        this.answer = answer;
    }

    public Deck getDeck() {
        return Deck.findById(deckId);
    }

    public void setDeck(Deck deck) {
        this.deckId = deck.id;
    }

    private void verifyLegalSaveState() {
        if (deckId == null || deckId < 1) {
            throw new IllegalStateException("Cannot insert card. Illegal deck id. deckId=" + deckId);
        }
    }

}


